package model.towers;

import model.enemies.IEnemy;
import model.surface.Grid;
import model.surface.Scale;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;

import com.example.towerdefence.R;

import controller.GameBoard;

/**
 * Helper class for TowerSprite class. It handles the rotation of the tower and
 * the upgrade and sell options.
 * 
 * @author EvilTeam
 * 
 */
public class TowerSpriteSupplier {

	private static final int RANGE_UPGRADE = 50;
	private static final int SHOOTING_SPEED_UPGRADE = 1;
	private static final int DAMAGE_UPGRADE = 5;
	private static final int MAXIMUM_UPGRADES = 2;
	private static final String UPGRADE_DENY_COLOR = "#73FF0000";
	private static final int UPGRADE_EXTRA_COST = 50;
	private static final Bitmap sellIcon = BitmapFactory.decodeResource(
			GameBoard.getRes(), R.drawable.sell);
	private static final Bitmap upgradeIcon = BitmapFactory.decodeResource(
			GameBoard.getRes(), R.drawable.upgrade);
	private static Scale scale = Scale.getInstanceOfScaleClass();
	private static boolean hasEnoughtMoney = true;

	/**
	 * Rotates the tower in the right direction when an enemy is in range
	 * depending on y axis point.
	 * 
	 * @param target
	 * @param tower
	 */
	public static void setTowerDirectionDependingOnY(IEnemy target, ITower tower) {
		int result = (int) (tower.getyAxisPoint() - target.getY());
		if (result > 0) {
			if (target.getX() < tower.getxAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(3);
			} else if (target.getX() > tower.getxAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(1);
			} else if (target.getX() > tower.getxAxisPoint()
					&& target.getX() < tower.getxAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(0);
			}
		} else {
			if (target.getX() < tower.getxAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(1);
			} else if (target.getX() > tower.getxAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(3);
			} else if (target.getX() > tower.getxAxisPoint()
					&& target.getX() < tower.getxAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(0);
			}
		}
	}

	/**
	 * Rotates the tower in the right direction when an enemy is in range
	 * depending on x axis point.
	 * 
	 * @param target
	 * @param tower
	 */
	public static void setTowerDirectionDependingOnX(IEnemy target, ITower tower) {
		int result = (int) (tower.getxAxisPoint() - target.getX());
		if (result > 0) {
			if (target.getY() < tower.getyAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(3);
			} else if (target.getY() > tower.getyAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(1);
			} else if (target.getY() < tower.getyAxisPoint()
					&& target.getY() > tower.getyAxisPoint()) {
				tower.setCurrentDirection(0);
				tower.setCurrentFrame(2);
			}
		} else {
			if (target.getY() < tower.getyAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(1);
			} else if (target.getY() > tower.getyAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(3);
			} else if (target.getY() < tower.getyAxisPoint()
					&& target.getY() > tower.getyAxisPoint()) {
				tower.setCurrentDirection(1);
				tower.setCurrentFrame(2);
			}
		}
	}

	/**
	 * Used to draw the sell icon in the range of the tower.
	 * 
	 * @param canvas
	 * @param tower
	 */
	public static void drawSellIcon(Canvas canvas, ITower tower) {

		tower.setScaledSellIcon(Bitmap.createScaledBitmap(sellIcon,
				scale.getScaledWidthForIcons(),
				scale.getScaledHeightForIcons(), true));

		Rect sourceRectangular = new Rect(0, 0, tower.getScaledSellIcon()
				.getWidth(), tower.getScaledSellIcon().getHeight());
		if (tower.getScaledSellIcon() != null) {
			if (tower.getyAxisPoint() >= Grid.getHeightOfTheCell()
					&& tower.getyAxisPoint() <= 2 * Grid.getHeightOfTheCell()) {
				Rect destinationRectangular = new Rect(
						(int) tower.getxAxisPoint()
								+ scale.scaledXPointForIcons() * 2,
						(int) tower.getyAxisPoint()
								- scale.scaledYPointForIcons() / 4,
						((int) tower.getxAxisPoint() + scale
								.scaledXPointForIcons() * 2)
								+ tower.getScaledSellIcon().getWidth() / 2,
						((int) tower.getyAxisPoint() - scale
								.scaledYPointForIcons() / 4)
								+ tower.getScaledSellIcon().getHeight() / 2);

				canvas.drawBitmap(tower.getScaledSellIcon(), sourceRectangular,
						destinationRectangular, null);
			} else {
				Rect destinationRectangular = new Rect(
						(int) tower.getxAxisPoint()
								- scale.scaledXPointForIcons(),
						(int) tower.getyAxisPoint()
								+ scale.scaledYPointForIcons() / 2,
						((int) tower.getxAxisPoint() - scale
								.scaledXPointForIcons())
								+ tower.getScaledSellIcon().getWidth() / 2,
						((int) tower.getyAxisPoint() + scale
								.scaledYPointForIcons() / 2)
								+ tower.getScaledSellIcon().getHeight() / 2);

				canvas.drawBitmap(tower.getScaledSellIcon(), sourceRectangular,
						destinationRectangular, null);
			}
		}
	}

	/**
	 * Used to draw upgrade icon in the range of the tower.
	 * 
	 * @param canvas
	 * @param tower
	 */
	public static void drawUpgradeIcon(Canvas canvas, ITower tower) {

		tower.setScaledUpgradeIcon(Bitmap.createScaledBitmap(upgradeIcon,
				scale.getScaledWidthForIcons(),
				scale.getScaledHeightForIcons(), true));

		Rect sourceRectangular = new Rect(0, 0, tower.getScaledUpgradeIcon()
				.getWidth(), tower.getScaledUpgradeIcon().getHeight());

		if (tower.getScaledUpgradeIcon() != null) {
			Rect destinationRectangular = null;
			if (tower.getyAxisPoint() >= Grid.getHeightOfTheCell()
					&& tower.getyAxisPoint() <= 2 * Grid.getHeightOfTheCell()) {
				destinationRectangular = new Rect((int) tower.getxAxisPoint()
						- scale.scaledXPointForIcons() * 4,
						(int) tower.getyAxisPoint()
								- scale.scaledYPointForIcons() / 4,
						((int) tower.getxAxisPoint() - scale
								.scaledXPointForIcons() * 4)
								+ tower.getScaledUpgradeIcon().getWidth() / 2,
						((int) tower.getyAxisPoint() - scale
								.scaledYPointForIcons() / 4)
								+ tower.getScaledUpgradeIcon().getHeight() / 2);

				canvas.drawBitmap(tower.getScaledUpgradeIcon(),
						sourceRectangular, destinationRectangular, null);
			} else {
				destinationRectangular = new Rect((int) tower.getxAxisPoint()
						- scale.scaledXPointForIcons(),
						(int) tower.getyAxisPoint()
								- scale.scaledYPointForIcons(),
						((int) tower.getxAxisPoint() - scale
								.scaledXPointForIcons())
								+ tower.getScaledUpgradeIcon().getWidth() / 2,
						((int) tower.getyAxisPoint() - scale
								.scaledYPointForIcons())
								+ tower.getScaledUpgradeIcon().getHeight() / 2);

				canvas.drawBitmap(tower.getScaledUpgradeIcon(),
						sourceRectangular, destinationRectangular, null);
			}
			if (tower.getNumberOfAllowedUpgrades() == MAXIMUM_UPGRADES)
				drawUpgradeDeny(canvas, destinationRectangular);
			if (!hasEnoughtMoney)
				drawUpgradeDeny(canvas, destinationRectangular);
			hasEnoughtMoney = true;
		}
	}

	/**
	 * Checks if some of the upgrade or the sell icon is touched.
	 * 
	 * @param x
	 * @param y
	 * @param tower
	 * @return
	 */
	public static boolean checkSellAndUpgradeIconsForTouch(float x, float y,
			ITower tower) {

		if (tower.getScaledSellIcon() == null
				|| tower.getScaledUpgradeIcon() == null)
			return false;

		if (tower.getyAxisPoint() >= Grid.getHeightOfTheCell()
				&& tower.getyAxisPoint() <= 2 * Grid.getHeightOfTheCell()) {
			if (x >= ((int) tower.getxAxisPoint() + scale
					.scaledXPointForIcons() * 2)
					&& x <= (((int) tower.getxAxisPoint() + scale
							.scaledXPointForIcons() * 2) + tower
							.getScaledSellIcon().getWidth() / 2)
					&& y >= ((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons() / 4)
					&& y <= (((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons() / 4) + tower
							.getScaledSellIcon().getHeight() / 2)) {
				sellTower(tower);
				return true;
			}
			if (x >= (((int) tower.getxAxisPoint() - scale
					.scaledXPointForIcons() * 4))
					&& x <= (((int) tower.getxAxisPoint() - scale
							.scaledXPointForIcons() * 4) + tower
							.getScaledUpgradeIcon().getWidth() / 2)
					&& y >= ((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons() / 4)
					&& y <= (((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons() / 4) + tower
							.getScaledUpgradeIcon().getHeight() / 2)) {
				upgradeTower(tower);
				return true;
			}
		} else {

			if (x >= ((tower.getxAxisPoint() - scale.scaledXPointForIcons()))
					&& x <= (((int) tower.getxAxisPoint() - scale
							.scaledXPointForIcons()) + tower
							.getScaledSellIcon().getWidth() / 2)
					&& y >= ((int) tower.getyAxisPoint() + scale
							.scaledYPointForIcons() / 2)
					&& y <= (((int) tower.getyAxisPoint() + scale
							.scaledYPointForIcons() / 2) + tower
							.getScaledSellIcon().getHeight() / 2)) {
				sellTower(tower);
				return true;
			}
			if (x >= ((tower.getxAxisPoint() - scale.scaledXPointForIcons()))
					&& x <= (((int) tower.getxAxisPoint() - scale
							.scaledXPointForIcons()) + tower
							.getScaledUpgradeIcon().getWidth() / 2)
					&& y >= ((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons())
					&& y <= (((int) tower.getyAxisPoint() - scale
							.scaledYPointForIcons()) + tower
							.getScaledUpgradeIcon().getHeight() / 2)) {
				upgradeTower(tower);
				return true;
			}
		}
		tower.setScaledSellIcon(null);
		tower.setScaledUpgradeIcon(null);
		return false;
	}

	/**
	 * Draws access deny circle around upgrade icon if the player doesn't have
	 * enough money or the tower has reached maximum upgrades.
	 * 
	 * @param canvas
	 * @param destinationRectangular
	 */
	private static void drawUpgradeDeny(Canvas canvas,
			Rect destinationRectangular) {
		Paint circlePaint = new Paint();
		circlePaint.setColor(Color.parseColor(UPGRADE_DENY_COLOR));
		canvas.drawCircle(destinationRectangular.exactCenterX(),
				destinationRectangular.exactCenterY(),
				destinationRectangular.width() / 2, circlePaint);
	}

	/**
	 * Upgrades the tower.
	 * 
	 * @param tower
	 */
	private static void upgradeTower(ITower tower) {
		if (GameBoard.getCurrentPlayer().getMoney() >= tower.getPrice()
				+ UPGRADE_EXTRA_COST
				&& tower.getNumberOfAllowedUpgrades() < 2) {
			int newMoney = GameBoard.getCurrentPlayer().getMoney()
					- (tower.getPrice() + UPGRADE_EXTRA_COST);
			GameBoard.getCurrentPlayer().setMoney(newMoney);
			tower.setDamage(tower.getDamage() + DAMAGE_UPGRADE);
			tower.setShootingSpeed(tower.getShootingSpeed() - SHOOTING_SPEED_UPGRADE);
			tower.setRange((tower.getRange() * scale.getScaleFactorForRange()) + RANGE_UPGRADE);
			tower.setNumberOfAllowedUpgrades(tower.getNumberOfAllowedUpgrades() + 1);
		} else {
			hasEnoughtMoney = false;
		}
	}

	/**
	 * Sells the tower.
	 * 
	 * @param tower
	 */
	private static void sellTower(ITower tower) {
		tower.setSold(true);
		tower.getStartShootingThread().stopShooting();
		int newMoney = GameBoard.getCurrentPlayer().getMoney()
				+ (tower.getPrice() / 2);
		GameBoard.getCurrentPlayer().setMoney(newMoney);
		Grid.emptyCell(tower.getxAxisPoint(), tower.getyAxisPoint());
	}
}
